home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / dev / gui / FoxGuiSource.lha / FoxLibSource / EditBox.c < prev    next >
C/C++ Source or Header  |  2001-07-07  |  48KB  |  1,671 lines

  1. /* FoxGUI - The fast, flexible, free Amiga GUI system
  2.     Copyright (C) 2001 Simon Fox (Foxysoft)
  3.  
  4. This library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2.1 of the License, or (at your option) any later version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  5. Foxysoft: www.foxysoft.co.uk      Email:simon@foxysoft.co.uk                */
  6.  
  7. /******************************************************************************
  8.  * Shared library code.  Cannot call functions which use exit() such as:
  9.  * printf(), fprintf()
  10.  *
  11.  * Otherwise:
  12.  * The linker returns "__XCEXIT undefined" and the program will fail.
  13.  * This is because you must not exit() a library!
  14.  *
  15.  * Also:
  16.  * proto/exec.h must be included instead of clib/exec_protos.h and
  17.  * __USE_SYSBASE must be defined.
  18.  *
  19.  * Otherwise:
  20.  * The linker returns "Absolute reference to symbol _SysBase" and the
  21.  * library crashes.  Presumably the same is true for the other protos.
  22.  ******************************************************************************/
  23.  
  24. #define __USE_SYSBASE
  25.  
  26. #ifdef __STORM__
  27.     #define AMIGA
  28. #endif
  29.  
  30. #include <proto/mathieeedoubbas.h>
  31. #include <stdlib.h>
  32. #include <math.h>
  33. #include <string.h>
  34.  
  35. #include <proto/exec.h>
  36. #include <proto/intuition.h>
  37. #include <intuition/sghooks.h>
  38. //include <utility/hooks.h>
  39. #include "/FoxInclude/foxgui.h"
  40. #include "FoxGuiTools.h"
  41.  
  42. #define GUIWIN(p) ((GuiWindow*)p->editbox.UserData)
  43.  
  44. static short Newoutside[] = { 1, 8,  1, 1, 15, 1, 15, 8, 1, 8 };
  45. static short Newarrow[]   = { 5, 3, 11, 3,  8, 6,  5, 3 };
  46.  
  47. static short Newoutside3D[] = { 1, 9,  1, 0, 16, 0, 16, 9, 1, 9 };
  48. static short Newarrow3D[]   = { 6, 3, 12, 3,  9, 6,  6, 3 };
  49.  
  50. static BOOL EditStatusStored = FALSE;
  51. static BOOL ListStatusStored = FALSE;
  52.  
  53. void FOXLIB RefreshEditBox(REGA0 EditBox *p)
  54.     {
  55.     Diagnostic("RefreshEditBox", ENTER, TRUE);
  56.     if (!p)
  57.         {
  58.         Diagnostic("RefreshEditBox", EXIT, FALSE);
  59.         return;
  60.         }
  61.     if (p->hidden == 0)
  62.         RefreshGList(&p->editbox, GUIWIN(p)->Win, NULL, 1);
  63.     Diagnostic("RefreshEditBox", EXIT, TRUE);
  64.     }
  65.  
  66. BOOL FOXLIB SetEditBoxCols(REGA0 EditBox *p, REGD0 int BorderCol, REGD1 int Bcol, REGD2 int Tcol)
  67.    {
  68.     int GadPos;
  69.    Diagnostic("SetEditBoxCols", ENTER, TRUE);
  70.    if (!p)
  71.       return Diagnostic("SetEditBoxCols", EXIT, FALSE);
  72.     if (p->hidden == 0)
  73.         GadPos = RemoveGList(GUIWIN(p)->Win, &p->editbox, 1);
  74.    p->Bcol = Bcol;
  75.     if (!(p->WidgetData->flags & THREED))
  76.         p->lborder.FrontPen = BorderCol;
  77.    p->Tcol = Tcol;
  78.  
  79.     if (p->strinfo.Extension)
  80.         {
  81.         p->strinfo.Extension->Pens[0] = Tcol;
  82.         p->strinfo.Extension->ActivePens[0] = Tcol;
  83.         if (!(p->WidgetData->flags & EB_CLEAR))
  84.             {
  85.             p->strinfo.Extension->Pens[1] = Bcol;
  86.             p->strinfo.Extension->ActivePens[1] = Bcol;
  87.             }
  88.         }
  89.  
  90.     if (p->hidden == 0)
  91.         {
  92.         AddGList(GUIWIN(p)->Win, &p->editbox, GadPos, 1, NULL);
  93.         RefreshEditBox(p);
  94.         }
  95.    return Diagnostic("SetEditBoxCols", EXIT, TRUE);
  96.    }
  97.  
  98. char* FOXLIB GetEditBoxText(REGA0 EditBox *p)
  99.    {
  100.    Diagnostic("GetEditBoxText", ENTER, TRUE);
  101.    if (!p)
  102.       {
  103.       Diagnostic("GetEditBoxText", EXIT, FALSE);
  104.       return NULL;
  105.       }
  106.    Diagnostic("GetEditBoxText", EXIT, TRUE);
  107.    return p->buffer;
  108.    }
  109.  
  110. int FOXLIB GetEditBoxInt(REGA0 EditBox *p)
  111.    {
  112.    Diagnostic("GetEditBoxInt", ENTER, TRUE);
  113.    if (!p)
  114.       {
  115.       Diagnostic("GetEditBoxInt", EXIT, FALSE);
  116.       return 0;
  117.       }
  118.    Diagnostic("GetEditBoxInt", EXIT, TRUE);
  119.    return atoi(p->buffer);
  120.    }
  121.  
  122. BOOL FOXLIB SetEditBoxText(REGA0 EditBox *p, REGA1 char *text)
  123.     {
  124.     int GadPos = -1;
  125.    Diagnostic("SetEditBoxText", ENTER, TRUE);
  126.    if (!p)
  127.       return Diagnostic("SetEditBoxText", EXIT, FALSE);
  128.     if (p->hidden == 0 && !(Gui.LibVersion < A3000 && p->list))
  129.         GadPos = RemoveGList(GUIWIN(p)->Win, &p->editbox, 1);
  130.    if (strlen(text) > p->len)
  131.         {
  132.       strncpy(p->buffer, text, p->len);
  133.         p->buffer[p->len] = '\0';
  134.         }
  135.    else
  136.       strcpy(p->buffer, text);
  137.     // Set the initial cursor position for the editbox to the character
  138.     // beyond the end of the string or to the first character if this is a
  139.     // list box.
  140.     ((struct StringInfo *)(p->editbox.SpecialInfo))->BufferPos = (p->list == NULL ? strlen(p->buffer) : 0);
  141.     if (p->hidden == 0)
  142.         {
  143.         AddGList(GUIWIN(p)->Win, &p->editbox, GadPos, 1, NULL);
  144.         RefreshGList(&p->editbox, GUIWIN(p)->Win, NULL, 1);
  145.         if (Gui.LibVersion < A3000 && p->list)
  146.             GadPos = RemoveGList(GUIWIN(p)->Win, &(p->editbox), 1);
  147.         }
  148.     return Diagnostic("SetEditBoxText", EXIT, TRUE);
  149.     }
  150.  
  151. BOOL FOXLIB SetEditBoxInt(REGA0 EditBox *p, REGD0 int num)
  152.    {
  153.    BOOL retval;
  154.    char str[12];
  155.    Diagnostic("SetEditBoxInt", ENTER, TRUE);
  156.    sprintf(str, "%d", num);
  157.    retval = SetEditBoxText(p, str);
  158.    return Diagnostic("SetEditBoxInt", EXIT, retval);
  159.    }
  160.  
  161. BOOL FOXLIB SetEditBoxDP(REGA0 EditBox *p, REGD0 int num)
  162.    {
  163.    Diagnostic("SetEditBoxDP", ENTER, TRUE);
  164.    if (!p)
  165.       return Diagnostic("SetEditBoxDP", EXIT, FALSE);
  166.    p->dp = num;
  167.    return Diagnostic("SetEditBoxDP", EXIT, TRUE);
  168.    }
  169.  
  170. void FOXLIB SortDDListBox(REGA0 DDListBox *p, REGD0 int flags)
  171.    {
  172.    struct ListElement *smallest, *start, *ptr, *smallestprev, *startprev, *ptrprev;
  173.    Diagnostic("SortDDListBox", ENTER, TRUE);
  174.    if ((!p) || !p->list)
  175.       {
  176.       Diagnostic("SortDDListBox", EXIT, FALSE);
  177.       return;
  178.       }
  179.    start = p->list->first;
  180.    startprev = NULL;
  181.    while (start)
  182.       {
  183.       smallest = start;
  184.       smallestprev = startprev;
  185.       ptr = start->Next;
  186.       ptrprev = start;
  187.       while (ptr)
  188.          {
  189.             if (flags & NUM_ASCENDING || flags & NUM_DESCENDING)
  190.                 {
  191.                 if (atoi(flags & NUM_ASCENDING ? ptr->string : smallest->string)
  192.                     < atoi(flags & NUM_ASCENDING ? smallest->string : ptr->string))
  193.                     {
  194.                 smallest = ptr;
  195.                 smallestprev = ptrprev;
  196.                     }
  197.                 }
  198.             else if (flags & IGNORE_CASE)
  199.                 {
  200.                 if (stricmp(flags & ASCENDING ? ptr->string : smallest->string, flags & ASCENDING ?
  201.                         smallest->string : ptr->string) < 0)
  202.                    {
  203.                    smallest = ptr;
  204.                    smallestprev = ptrprev;
  205.                 }
  206.                 }
  207.             else if (strcmp(flags & ASCENDING ? ptr->string : smallest->string, flags & ASCENDING ?
  208.                     smallest->string : ptr->string) < 0)
  209.                {
  210.                smallest = ptr;
  211.                smallestprev = ptrprev;
  212.             }
  213.          ptrprev = ptr;
  214.          ptr = ptr->Next;
  215.          }
  216.       if (smallest != start)
  217.          {
  218.          if (smallestprev)
  219.             smallestprev->Next = smallest->Next;
  220.          else
  221.             p->list->first = smallest->Next;
  222.          if (startprev)
  223.             startprev->Next = smallest;
  224.          else
  225.             p->list->first = smallest;
  226.          smallest->Next = start;
  227.          }
  228.       else
  229.          start = start->Next;
  230.       if (start == p->list->first)
  231.          startprev = NULL;
  232.       else
  233.          for (startprev = p->list->first; startprev->Next != start;)
  234.             startprev = startprev->Next;
  235.       }
  236.    for (flags = 1, ptr = p->list->first; ptr != NULL; ptr = ptr->Next, flags++)
  237.       ptr->Itemnum = flags;
  238.    Diagnostic("SortDDListBox", EXIT, TRUE);
  239.    }
  240.  
  241. void DisableAllDDListBoxes(BOOL redraw)
  242.    {
  243.    struct EditBoxStruct *p;
  244.    Diagnostic("DisableAllDDListBoxes", ENTER, TRUE);
  245.    p = Gui.FirstEditBox;
  246.    while (p)
  247.       {
  248.       DisableDDListBox(p, redraw);
  249.       p = p->next;
  250.       }
  251.    Diagnostic("DisableAllDDListBoxes", EXIT, TRUE);
  252.    }
  253.  
  254. void DisableWinDDListBoxes(GuiWindow *c, BOOL redraw)
  255.    {
  256.    struct EditBoxStruct *p;
  257.    Diagnostic("DisableWinDDListBoxes", ENTER, TRUE);
  258.    p = Gui.FirstEditBox;
  259.    while (p)
  260.       {
  261.       if (GUIWIN(p) == c)
  262.          DisableDDListBox(p, redraw);
  263.       p = p->next;
  264.       }
  265.    Diagnostic("DisableWinDDListBoxes", EXIT, TRUE);
  266.    }
  267.  
  268. void DisableEditBox(EditBox *p, BOOL redraw)
  269.     {
  270.     if (p && p->enabled && !(p->list))
  271.         {
  272.         if (p->hidden == 0)
  273.             DisableGadget(&p->editbox, GUIWIN(p)->Win, redraw);
  274.         else
  275.             p->editbox.Flags |= GFLG_DISABLED;
  276.         p->enabled = FALSE;
  277.         }
  278.     }
  279.  
  280. void DisableDDListBox(DDListBox *p, BOOL redraw)
  281.     {
  282.     if (p && p->enabled && p->list)
  283.         {
  284.         if (Gui.LibVersion >= A3000)
  285.             {
  286.             if (p->hidden == 0)
  287.                 DisableGadget(&p->editbox, GUIWIN(p)->Win, redraw);
  288.             else
  289.                 p->editbox.Flags |= GFLG_DISABLED;
  290.             }
  291.         else
  292.             {
  293.             // For an A500 the gadget isn't in the list so we need to do everything in a different order
  294.             struct Gadget *gad = &(p->editbox);
  295.             struct Window *win = GUIWIN(p)->Win;
  296.             gad->Flags |= GFLG_DISABLED;
  297.             if (redraw && p->hidden == 0)
  298.                 {
  299.                 AddGadget(win, gad, 0);
  300.                 RefreshGList(gad, win, NULL, 1L);
  301.                 RemoveGadget(win, gad);
  302.                 }
  303.             }
  304.         p->enabled = FALSE;
  305.         }
  306.     }
  307.  
  308. void DisableAllEditBoxes(BOOL redraw)
  309.    {
  310.    struct EditBoxStruct *p;
  311.    Diagnostic("DisableAllEditBoxes", ENTER, TRUE);
  312.    p = Gui.FirstEditBox;
  313.    while (p)
  314.       {
  315.       DisableEditBox(p, redraw);
  316.       p = p->next;
  317.       }
  318.    Diagnostic("DisableAllEditBoxes", EXIT, TRUE);
  319.    }
  320.  
  321. void DisableWinEditBoxes(GuiWindow *c, BOOL redraw)
  322.    {
  323.    struct EditBoxStruct *p;
  324.    Diagnostic("DisableWinEditBoxes", ENTER, TRUE);
  325.    p = Gui.FirstEditBox;
  326.    while (p)
  327.       {
  328.       if (GUIWIN(p) == c)
  329.          DisableEditBox(p, redraw);
  330.       p = p->next;
  331.       }
  332.    Diagnostic("DisableWinEditBoxes", EXIT, TRUE);
  333.    }
  334.  
  335. void EnableEditBox(EditBox *p, BOOL redraw)
  336.     {
  337.     if (p && p->enabled == FALSE && !(p->list))
  338.         {
  339.         if (p->hidden == 0)
  340.             EnableGadget(&p->editbox, GUIWIN(p)->Win, redraw);
  341.         else
  342.             p->editbox.Flags ^= GFLG_DISABLED;
  343.         p->enabled = TRUE;
  344.         }
  345.     }
  346.  
  347. void EnableDDListBox(DDListBox *p, BOOL redraw)
  348.     {
  349.     if (p && p->enabled == FALSE && p->list)
  350.         {
  351.         if (Gui.LibVersion >= A3000)
  352.             {
  353.             if (p->hidden == 0)
  354.                 EnableGadget(&p->editbox, GUIWIN(p)->Win, redraw);
  355.             else
  356.                 p->editbox.Flags ^= GFLG_DISABLED;
  357.             }
  358.         else
  359.             {
  360.             // For an A500 the gadget isn't in the list so we need to do everything in a different order
  361.             struct Gadget *gad = &(p->editbox);
  362.             struct Window *win = GUIWIN(p)->Win;
  363.             gad->Flags ^= GFLG_DISABLED;
  364.             if (redraw && p->hidden == 0)
  365.                 {
  366.                 AddGadget(win, gad, 0);
  367.                 RefreshGList(gad, win, NULL, 1L);
  368.                 RemoveGadget(win, gad);
  369.                 }
  370.             }
  371.         p->enabled = TRUE;
  372.         }
  373.     }
  374.  
  375. void EnableAllEditBoxes(BOOL redraw)
  376.    {
  377.    struct EditBoxStruct *p;
  378.    Diagnostic("EnableAllEditBoxes", ENTER, TRUE);
  379.    p = Gui.FirstEditBox;
  380.    while (p)
  381.       {
  382.       EnableEditBox(p, redraw);
  383.       p = p->next;
  384.       }
  385.    Diagnostic("EnableAllEditBoxes", EXIT, TRUE);
  386.    }
  387.  
  388. void EnableWinEditBoxes(GuiWindow *c, BOOL redraw)
  389.    {
  390.    struct EditBoxStruct *p;
  391.    Diagnostic("EnableWinEditBoxes", ENTER, TRUE);
  392.    p = Gui.FirstEditBox;
  393.    while (p)
  394.       {
  395.       if (GUIWIN(p) == c)
  396.          EnableEditBox(p, redraw);
  397.       p = p->next;
  398.       }
  399.    Diagnostic("EnableWinEditBoxes", EXIT, TRUE);
  400.    }
  401.  
  402. void EnableAllDDListBoxes(BOOL redraw)
  403.    {
  404.    struct EditBoxStruct *p;
  405.    Diagnostic("EnableAllDDListBoxes", ENTER, TRUE);
  406.    p = Gui.FirstEditBox;
  407.    while (p)
  408.       {
  409.       EnableDDListBox(p, redraw);
  410.       p = p->next;
  411.       }
  412.    Diagnostic("EnableAllDDListBoxes", EXIT, TRUE);
  413.    }
  414.  
  415. void EnableWinDDListBoxes(GuiWindow *c, BOOL redraw)
  416.    {
  417.    struct EditBoxStruct *p;
  418.    Diagnostic("EnableWinDDListBoxes", ENTER, TRUE);
  419.    p = Gui.FirstEditBox;
  420.    while (p)
  421.       {
  422.       if (GUIWIN(p) == c)
  423.          EnableDDListBox(p, redraw);
  424.       p = p->next;
  425.       }
  426.    Diagnostic("EnableWinDDListBoxes", EXIT, TRUE);
  427.    }
  428.  
  429. static BOOL FindPreviousNext(EditBox *p, BOOL *prefound, BOOL *nextfound, UWORD *prepos, UWORD *nextpos)
  430.     {
  431.     struct Window *w = GUIWIN(p)->Win;
  432.     struct Gadget *g = w->FirstGadget;
  433.     UWORD pos = 0;
  434.     BOOL found = FALSE;
  435.  
  436.     *prefound = *nextfound = FALSE;
  437.     *prepos = *nextpos = 0;
  438.     while (g && !found)
  439.         {
  440.         if (g == &p->editbox)
  441.             found = TRUE;
  442.         else if (p->next && g == &p->next->editbox)
  443.             {
  444.             *nextfound = TRUE;
  445.             *nextpos = pos;
  446.             }
  447.         else if (p->previous && g == &p->previous->editbox)
  448.             {
  449.             *prefound = TRUE;
  450.             *prepos = pos;
  451.             }
  452.         g = g->NextGadget;
  453.         pos++;
  454.         }
  455.     return found;
  456.     }
  457.  
  458. BOOL ShowEditBox(EditBox *p)
  459.     {
  460.     Diagnostic("ShowEditBox", ENTER, TRUE);
  461.     if (p && !p->list)
  462.         {
  463.         // First check whether the gadget is hidden.  At the same time, we'll look for the previous and
  464.         // next edit boxes in our list so that we can add it back in the same position it was removed from
  465.         // to preserve the tab order.
  466.         struct Window *w = GUIWIN(p)->Win;
  467.         BOOL prefound, nextfound;
  468.         UWORD pos, prepos, nextpos;
  469.  
  470.         if (p->hidden == 1) // The editbox is really hidden
  471.             if ((!ISGUIWINDOW(p->WidgetData->Parent)) && ((Frame *) p->WidgetData->Parent)->hidden != 0)
  472.                 p->hidden = -1; // The editbox is in a hidden frame so it will remain hidden
  473.             else
  474.                 {
  475.                 FindPreviousNext(p, &prefound, &nextfound, &prepos, &nextpos);
  476.                 // We need to add the gadget
  477.                 if (nextfound)
  478.                     pos = nextpos + 1;
  479.                 else if (prefound)
  480.                     pos = prepos;
  481.                 else
  482.                     pos = (unsigned short) ~0; // Add to the end of the list because we couldn't find the right place.
  483.                 AddGadget(w, &p->editbox, pos);
  484.                 p->hidden = 0;
  485.                 }
  486.         if (p->hidden == 0)
  487.             // refresh the gadget
  488.             RefreshGList(&p->editbox, w, NULL, 1);
  489.         return Diagnostic("ShowEditBox", EXIT, TRUE);
  490.         }
  491.     return Diagnostic("ShowEditBox", EXIT, FALSE);
  492.     }
  493.  
  494. BOOL HideEditBox(EditBox *p)
  495.     {
  496.     Diagnostic("HideEditBox", ENTER, TRUE);
  497.     if (p && !p->list)
  498.         {
  499.         if (p->hidden == 0)
  500.             {
  501.             int fontheight;
  502.             struct TextAttr *font = GUIWIN(p)->ParentScreen->Font;
  503.  
  504.             RemoveGadget(GUIWIN(p)->Win, &(p->editbox));
  505.             if (font)
  506.                 fontheight = font->ta_YSize;
  507.             else
  508.                 fontheight = GuiFont.ta_YSize;
  509.             AreaColFill(GUIWIN(p)->Win->RPort, p->WidgetData->left, p->WidgetData->top, p->WidgetData->width, fontheight + 2,
  510.                     GetBackCol(p->WidgetData->Parent));
  511.             }
  512.         p->hidden = 1;
  513.         return Diagnostic("HideEditBox", EXIT, TRUE);
  514.         }
  515.     return Diagnostic("HideEditBox", EXIT, FALSE);
  516.     }
  517.  
  518. void DestroyEditBox(EditBox *p, BOOL refresh)
  519.    {
  520.    Diagnostic("DestroyEditBox", ENTER, TRUE);
  521.    if (p && !(p->list))
  522.       {
  523.         Frame *Child; // Could be any type of control
  524.         struct EditBoxStruct *n = p->next;
  525.  
  526.         if (p == Gui.FirstEditBox)
  527.             Gui.FirstEditBox = n;
  528.         if (n)
  529.             n->previous = p->previous;
  530.         if (p->previous)
  531.             p->previous->next = n;
  532.  
  533.         if (p->hidden == 0)
  534.             {
  535.             if (refresh)
  536.                 HideEditBox(p);
  537.             else
  538.                 RemoveGadget(GUIWIN(p)->Win, &(p->editbox));
  539.             }
  540.         if (p->strinfo.Extension)
  541.             {
  542.             if (p->strinfo.Extension->EditHook)
  543.                 {
  544.                 GuiFree(p->strinfo.Extension->EditHook);
  545.               GuiFree(p->strinfo.Extension->WorkBuffer);
  546.                 }
  547.             GuiFree(p->strinfo.Extension);
  548.             }
  549.       if (p->buffer)
  550.          GuiFree(p->buffer);
  551.       if (p->undobuffer)
  552.          GuiFree(p->undobuffer);
  553.  
  554.         if (p->WidgetData->os)
  555.             GuiFree(p->WidgetData->os);
  556.         Child = p->WidgetData->ChildWidget;
  557.         while (Child)
  558.             {
  559.             void *next = Child->WidgetData->NextWidget;
  560.             Child->WidgetData->ParentControl = NULL; // Otherwise destroy will fail.
  561.             Destroy(Child, refresh);
  562.             Child = next;
  563.             }
  564.       GuiFree(p->WidgetData);
  565.       GuiFree(p);
  566.       }
  567.    Diagnostic("DestroyEditBox", EXIT, TRUE);
  568.    }
  569.  
  570. void DestroyAllEditBoxes(BOOL refresh)
  571.    {
  572.    struct EditBoxStruct *p;
  573.    Diagnostic("DestroyAllEditBoxes", ENTER, TRUE);
  574.    p = Gui.FirstEditBox;
  575.    while (p)
  576.       {
  577.         if (!p->list)
  578.             {
  579.           DestroyEditBox((EditBox *) p, refresh);
  580.             p = Gui.FirstEditBox;
  581.             }
  582.         else
  583.           p = p->next;
  584.       }
  585.    Diagnostic("DestroyAllEditBoxes", EXIT, TRUE);
  586.    }
  587.  
  588. void DestroyWinEditBoxes(GuiWindow *c, BOOL refresh)
  589.    {
  590.     BOOL message = FALSE;
  591.    struct EditBoxStruct *p;
  592.    Diagnostic("DestroyWinEditBoxes", ENTER, TRUE);
  593.    p = Gui.FirstEditBox;
  594.    while (p)
  595.       {
  596.       if (GUIWIN(p) == c && (!p->list))
  597.             {
  598.          DestroyEditBox((EditBox *) p, refresh);
  599.             message = TRUE;
  600.             p = Gui.FirstEditBox;
  601.             }
  602.         else
  603.             p = p->next;
  604.       }
  605.     if (Gui.CleanupFlag && message)
  606.         SetLastErr("Window closed before all of its edit boxes were destroyed.");
  607.    Diagnostic("DestroyWinEditBoxes", EXIT, TRUE);
  608.    }
  609.  
  610. ULONG hook_EditFloat(struct Hook *hook, struct SGWork *sgw, ULONG *msg)
  611.     {
  612.     if (*msg == SGH_KEY)
  613.         {
  614.         if (sgw->EditOp == EO_REPLACECHAR || sgw->EditOp == EO_INSERTCHAR)
  615.             {
  616.             int ok = FALSE, l;
  617.             if (sgw->Code >= '0' && sgw->Code <= '9')
  618.                 ok = TRUE;
  619.             else
  620.                 switch (sgw->Code)
  621.                     {
  622.                     case '+':
  623.                     case '-':
  624.                         if (sgw->BufferPos == 1)
  625.                             ok = TRUE;
  626.                         break;
  627.                     case '.':
  628.                         ok = TRUE;
  629.                         for (l = 0; l < sgw->NumChars; l++)
  630.                             if (sgw->WorkBuffer[l] == '.' && l != sgw->BufferPos - 1)
  631.                                 ok = FALSE;
  632.                     default:
  633.                         break;
  634.                     };
  635.             if (!ok)
  636.                 {
  637.                 sgw->Actions |= SGA_BEEP;
  638.                 sgw->Actions &= ~SGA_USE;
  639.                 }
  640.             }
  641.         return ~0L;
  642.         }
  643.     else
  644.         return 0;
  645.     }
  646.  
  647. ULONG hook_ListBox(struct Hook *hook, struct SGWork *sgw, ULONG *msg)
  648.     {
  649.     if (*msg == SGH_KEY)
  650.         {
  651.         if (sgw->EditOp == EO_REPLACECHAR || sgw->EditOp == EO_INSERTCHAR)
  652.             ListBoxKeyPress = sgw->Code;
  653.         sgw->Actions &= ~SGA_USE;
  654.         return ~0L;
  655.         }
  656.     else
  657.         return 0;
  658.     }
  659.  
  660. /*    Don't ask me what this does - it's to save having to write a bit of
  661.     machine code to do the same thing (whatever that is!).  For a brief
  662.     description see p.165 of RKRM: Libraries.
  663.     Note also that this bit of code creates a warning 154 which I have only
  664.     managed to get rid of by adding a -j154 option to the compile string for
  665.     this file in the Makefile. */
  666.  
  667. #ifdef AMIGA
  668. unsigned long __saveds __asm hookEntry(register __a0 struct Hook *hookptr, register __a2 void *object, register __a1 void *message)
  669.     {
  670.     return ((*hookptr->h_SubEntry) (hookptr, object, message));
  671.     }
  672. #endif
  673.  
  674. static void resizeeditbox(EditBox *eb, int x, int y, int len, BOOL eraseold, BOOL ForList, BOOL ForSubList)
  675.     {
  676.     unsigned short fontheight;
  677.  
  678.     if (GUIWIN(eb)->ParentScreen->Font)
  679.         fontheight = GUIWIN(eb)->ParentScreen->Font->ta_YSize;
  680.     else
  681.         fontheight = GuiFont.ta_YSize;
  682.  
  683.     /*    If the edit box is in a coloured frame then no need to blank it because the parent frame will
  684.         blank it's entire contents. */
  685.     if (eraseold && GetBackCol(eb->WidgetData->Parent) == GUIWIN(eb)->Win->RPort->BgPen)
  686.         {
  687.         AreaBlank(GUIWIN(eb)->Win->RPort, eb->WidgetData->left, eb->WidgetData->top, eb->WidgetData->width +
  688.                 ((ForList && !ForSubList) ? DD_LIST_BOX_BUTTON_WIDTH : 0), fontheight + 2);
  689.         if (eb->editbox.GadgetText)
  690.             {
  691.             int penhold;
  692.  
  693.             penhold = eb->editbox.GadgetText->FrontPen;
  694.             eb->editbox.GadgetText->FrontPen = GUIWIN(eb)->Win->RPort->BgPen;
  695.             PrintIText(GUIWIN(eb)->Win->RPort, eb->editbox.GadgetText, eb->editbox.LeftEdge,
  696.                     eb->editbox.TopEdge);
  697.             eb->editbox.GadgetText->FrontPen = penhold;
  698.             }
  699.         }
  700.  
  701.     eb->WidgetData->left = x;
  702.     eb->WidgetData->top = y;
  703.     eb->WidgetData->width = len;
  704.     eb->WidgetData->height = fontheight + 2;
  705.     eb->editbox.Width = len - (eb->WidgetData->flags & THREED ? 4 : 2);
  706.     eb->editbox.LeftEdge = x + (eb->WidgetData->flags & THREED ? 2 : 1);
  707.     eb->editbox.TopEdge = y + 1;
  708.  
  709.     if (eb->WidgetData->flags & THREED)
  710.         {
  711.         MakeBevel(&eb->lborder, &eb->dborder, eb->points, -2, -1, len, fontheight + 2, FALSE);
  712.         if (ForList && !ForSubList)
  713.             eb->dborder.NextBorder = &(eb->bb1);
  714.         }
  715.     else
  716.         {
  717.         eb->points[2] = eb->points[4] = eb->points[1] = eb->points[3] = eb->points[9] = eb->points[11] = 0;
  718.         // 0 to fontheight+1 makes a height of fontheight+2
  719.         eb->points[5]  = eb->points[7]  = eb->points[13] = eb->points[15] = fontheight + 1;
  720.         eb->points[0]  = eb->points[6]  = eb->points[8]  = eb->points[14] = len - 1;
  721.         eb->points[10] = eb->points[12] = len + DD_LIST_BOX_BUTTON_WIDTH - 1;
  722.         }
  723.     eb->arrow.LeftEdge = eb->bb1.LeftEdge = eb->bb2.LeftEdge = len - (eb->WidgetData->flags & THREED ? 2 : 1);
  724.     }
  725.  
  726. void ResizeEditBox(EditBox *eb, int x, int y, int len, BOOL eraseold)
  727.     {
  728.     BOOL forsublist = FALSE;
  729.     if (eb->list)
  730.         if (eb->list->Parent)
  731.             forsublist = TRUE;
  732.     resizeeditbox(eb, x, y, len, eraseold, (eb->list != NULL), forsublist);
  733.     }
  734.  
  735.  
  736. /*    The top, left hand corner of the editbox border will be at the EXACT
  737.     position specified in the x and y parameters passed to this function.
  738.  
  739.     The coordinates of the border, the pre-text and the post-text for a
  740.     new edit box are identical to those of an output box which is created
  741.     with the same parameters.  This has been THOROUGHLY tested and works
  742.     whether or not the window has a title bar and independantly of whether
  743.     or not the output box has a border.
  744.  
  745.     DO NOT CHANGE ONE WITHOUT CHANGING THE OTHER - PREFERABLY DON'T CHANGE! */
  746.  
  747. static EditBox* CreateEditBox(void *Parent, int x, int y, int len, int buflen, int BorderCol, int Bcol, int Tcol, int type, int id, BOOL (* __far __stdargs callfn)(EditBox*), BOOL ForList, BOOL ForSubList, long flags)
  748.    {
  749.    EditBox *p;
  750.     GuiWindow *win;
  751.     struct TextAttr *font;
  752.     unsigned short fontheight;
  753.     Frame *ParentFrame = NULL;
  754.  
  755.    Diagnostic("CreateEditBox", ENTER, TRUE);
  756.  
  757.     if (!Parent)
  758.         {
  759.        Diagnostic("CreateEditBox", EXIT, FALSE);
  760.         return NULL;
  761.         }
  762.  
  763.     if (!ISGUIWINDOW(Parent))
  764.         {
  765.         ParentFrame = (Frame *) Parent;
  766.         x += ParentFrame->button.LeftEdge;
  767.         y += ParentFrame->button.TopEdge;
  768.         win = (GuiWindow *) ParentFrame->button.UserData;
  769.         }
  770.     else
  771.         win = (GuiWindow *) Parent;
  772.     font = win->ParentScreen->Font;
  773.     if (font)
  774.         fontheight = font->ta_YSize;
  775.     else
  776.         fontheight = GuiFont.ta_YSize;
  777.  
  778.    p = (EditBox *) GuiMalloc(sizeof(struct EditBoxStruct), 0);
  779.    if (!p)
  780.       {
  781.       Diagnostic("CreateEditBox", EXIT, FALSE);
  782.       return NULL;
  783.       }
  784.    p->WidgetData = (Widget *) GuiMalloc(sizeof(Widget), 0);
  785.    if (!p->WidgetData)
  786.       {
  787.         GuiFree(p);
  788.       Diagnostic("CreateEditBox", EXIT, FALSE);
  789.       return NULL;
  790.       }
  791.     if (ForList)
  792.         p->WidgetData->ObjectType = DDListBoxObject;
  793.     else
  794.         p->WidgetData->ObjectType = EditBoxObject;
  795.     memset(&(p->strinfo), 0, sizeof(struct StringInfo));
  796.     if (ParentFrame && ParentFrame->hidden != 0)
  797.         p->hidden = -1;
  798.     else
  799.         p->hidden = 0;
  800.     if (ParentFrame && (flags & S_AUTO_SIZE) && !(ParentFrame->WidgetData->flags & S_AUTO_SIZE))
  801.         flags ^= S_AUTO_SIZE;
  802.     p->WidgetData->flags = flags;
  803.     p->WidgetData->Parent = Parent;
  804.     p->WidgetData->NextWidget = NULL;
  805.     p->WidgetData->ChildWidget = NULL;
  806.     p->id = id;
  807.    p->enabled = p->OldStatus = TRUE;
  808.    p->NextAssociated = p->PreviousAssociated = NULL;
  809.    p->len = min(buflen, MAX_EDIT_BOX_LEN);
  810.     if (flags & S_AUTO_SIZE)
  811.         {
  812.         if (!(p->WidgetData->os = (OriginalSize *) GuiMalloc(sizeof(OriginalSize), 0)))
  813.             {
  814.             GuiFree(p->WidgetData);
  815.             GuiFree(p);
  816.             Diagnostic("CreateEditBox", EXIT, FALSE);
  817.             return NULL;
  818.             }
  819.         p->WidgetData->os->left = x;
  820.         p->WidgetData->os->top = y;
  821.         p->WidgetData->os->width = len;
  822.         p->WidgetData->os->height = fontheight + 2; // This one will never change for edit boxes.
  823.         }
  824.     else
  825.         p->WidgetData->os = NULL;
  826.    if (ForSubList)
  827.         {
  828.       p->buffer = p->undobuffer = NULL;
  829.         }
  830.    else
  831.       {
  832.       p->buffer = (char *) GuiMalloc((p->len + 1) * sizeof(char), MEMF_CLEAR);
  833.       if (!(p->buffer))
  834.          {
  835.             if (p->WidgetData->os)
  836.                 GuiFree(p->WidgetData->os);
  837.          GuiFree(p->WidgetData);
  838.          GuiFree(p);
  839.          Diagnostic("CreateEditBox", EXIT, FALSE);
  840.          return NULL;
  841.          }
  842.       p->undobuffer = (char *) GuiMalloc((p->len + 1) * sizeof(char), MEMF_CLEAR);
  843.       if (!(p->undobuffer))
  844.          {
  845.          GuiFree(p->buffer);
  846.             if (p->WidgetData->os)
  847.                 GuiFree(p->WidgetData->os);
  848.          GuiFree(p->WidgetData);
  849.          GuiFree(p);
  850.          Diagnostic("CreateEditBox", EXIT, FALSE);
  851.          return NULL;
  852.          }
  853.         // Only allocate memory for the StringExtend structure if the machine
  854.         // is capable of using it!
  855.         if (Gui.LibVersion >= A3000)
  856.             {
  857.             p->strinfo.Extension = (struct StringExtend *) GuiMalloc(sizeof(struct StringExtend), MEMF_CLEAR);
  858.             if (!(p->strinfo.Extension))
  859.                 {
  860.                 GuiFree(p->undobuffer);
  861.                 GuiFree(p->buffer);
  862.                 if (p->WidgetData->os)
  863.                     GuiFree(p->WidgetData->os);
  864.              GuiFree(p->WidgetData);
  865.                 GuiFree(p);
  866.                 Diagnostic("CreateEditBox", EXIT, FALSE);
  867.              return NULL;
  868.                 }
  869.             if (type == FLOAT_EDIT || type == NO_EDIT)
  870.                 {
  871.                 p->strinfo.Extension->EditHook = (struct Hook *) GuiMalloc(sizeof(struct Hook), 0);
  872.                 if (!(p->strinfo.Extension->EditHook))
  873.                     {
  874.                     GuiFree(p->strinfo.Extension);
  875.                  GuiFree(p->undobuffer);
  876.                  GuiFree(p->buffer);
  877.                     if (p->WidgetData->os)
  878.                         GuiFree(p->WidgetData->os);
  879.                  GuiFree(p->WidgetData);
  880.                  GuiFree(p);
  881.                  Diagnostic("CreateEditBox", EXIT, FALSE);
  882.                  return NULL;
  883.                     }
  884.               p->strinfo.Extension->WorkBuffer = (char *) GuiMalloc((p->len + 1) * sizeof(char), 0);
  885.               if (!(p->strinfo.Extension->WorkBuffer))
  886.                  {
  887.                     GuiFree(p->strinfo.Extension->EditHook);
  888.                     GuiFree(p->strinfo.Extension);
  889.                  GuiFree(p->undobuffer);
  890.                  GuiFree(p->buffer);
  891.                     if (p->WidgetData->os)
  892.                         GuiFree(p->WidgetData->os);
  893.                  GuiFree(p->WidgetData);
  894.                  GuiFree(p);
  895.                  Diagnostic("CreateEditBox", EXIT, FALSE);
  896.                  return NULL;
  897.                  }
  898.                 }
  899.             }
  900.       }
  901.  
  902.     p->lborder.FrontPen = BorderCol;
  903.     p->lborder.DrawMode = JAM1;
  904.     /* The leftedge and topedge of the border are relative to the leftedge and top edge of the string
  905.         gadget.  For a 2D editbox, the string gadget is at x+1, y+1 so the border needs to be at -1,-1
  906.         to put the top left corner of the border at x, y. */
  907.    p->lborder.LeftEdge = p->lborder.TopEdge = -1;
  908.    p->lborder.XY = p->points;
  909.  
  910.     p->editbox.UserData = (APTR) win;
  911.     p->editbox.GadgetText = NULL;
  912.     resizeeditbox(p, x, y, len, FALSE, ForList, ForSubList);
  913.  
  914.    if (ForList && !ForSubList)
  915.       {
  916.         if (!(flags & THREED))
  917.             {
  918.           p->lborder.Count = 8;
  919.           p->lborder.NextBorder = &(p->bb1);
  920.             }
  921.         if (Gui.LibVersion >= A3000)
  922.             p->strinfo.Extension->InitialModes = SGM_REPLACE;
  923.       }
  924.    else if (ForSubList)
  925.         {
  926.       p->lborder.Count = 0;
  927.       p->lborder.NextBorder = NULL;
  928.         }
  929.    else if (!(flags & THREED))
  930.         {
  931.         p->lborder.Count = 5;
  932.         p->lborder.NextBorder = NULL;
  933.         }
  934.  
  935.    p->list      = NULL;
  936.    p->valifn    = callfn;
  937.    p->type      = type;
  938.    p->Bcol      = Bcol;
  939.    p->Tcol      = Tcol;
  940.    p->dp        = 2;
  941.    p->previous  = NULL;
  942.    p->next      = Gui.FirstEditBox;
  943.    p->arrow.Count      = 4;
  944.    p->bb1.Count        = p->bb2.Count = 3;
  945.    p->bb1.NextBorder   = &(p->bb2);
  946.    p->bb2.NextBorder   = &(p->arrow);
  947.    p->arrow.NextBorder = NULL;
  948.    p->bb1.FrontPen     = Gui.HiPen;
  949.    p->bb2.FrontPen     = p->arrow.FrontPen = Gui.LoPen;
  950.    p->arrow.DrawMode   = p->bb1.DrawMode = p->bb2.DrawMode = JAM1;
  951.    p->arrow.TopEdge    = p->bb1.TopEdge  = p->bb2.TopEdge  = -1;
  952.    p->bb1.XY           = (flags & THREED ? Newoutside3D : Newoutside);
  953.    p->bb2.XY           = (flags & THREED ? &(Newoutside3D[4]) : &(Newoutside[4]));
  954.    p->arrow.XY         = (flags & THREED ? Newarrow3D : Newarrow);
  955.  
  956.     p->editbox.NextGadget = NULL;
  957.     p->editbox.Height = fontheight;
  958.     p->editbox.Flags = GFLG_GADGHCOMP | GFLG_TABCYCLE | (Gui.LibVersion == A3000 ? 0 : GFLG_STRINGEXTEND);
  959.     p->editbox.Activation = GACT_RELVERIFY | GACT_IMMEDIATE | (type == INT_EDIT ? GACT_LONGINT : 0) | (Gui.LibVersion >= A3000 ? GACT_STRINGEXTEND : 0);
  960.     p->editbox.GadgetType = GTYP_STRGADGET;
  961.     p->editbox.GadgetRender = &(p->lborder);
  962.     p->editbox.SelectRender = NULL;
  963.     p->editbox.MutualExclude = 0;
  964.     p->editbox.SpecialInfo = &(p->strinfo);
  965.     p->editbox.GadgetID = 0;
  966.     p->strinfo.Buffer = p->buffer;
  967.     p->strinfo.UndoBuffer = p->undobuffer;
  968.     /*    A500's require 1 extra unused character otherwise any text written to the last character will
  969.         not get cleared if shorter text is written into the box. */
  970.     p->strinfo.MaxChars = p->len + (Gui.LibVersion < A3000 ? 1 : 0);
  971.  
  972.    if (Gui.LibVersion >= A3000 && !ForSubList)
  973.         {
  974.         p->strinfo.Extension->Pens[0] = Tcol;
  975.         p->strinfo.Extension->Pens[1] = (flags & EB_CLEAR ? GetBackCol(Parent) : Bcol);
  976.         p->strinfo.Extension->ActivePens[0] = Tcol;
  977.         p->strinfo.Extension->ActivePens[1] = p->strinfo.Extension->Pens[1];
  978.         }
  979.  
  980.     if (Gui.LibVersion >= A3000 && (type == FLOAT_EDIT || type == NO_EDIT) && !ForSubList)
  981.         {
  982.         memset(p->strinfo.Extension->WorkBuffer, 0, (p->len + 1) * sizeof(char));
  983.         p->strinfo.Extension->EditHook->h_Entry = hookEntry;
  984.         p->strinfo.Extension->EditHook->h_SubEntry = (type == FLOAT_EDIT ? hook_EditFloat : hook_ListBox);
  985.         p->strinfo.Extension->EditHook->h_Data = 0;
  986.         }
  987.  
  988.    if (Gui.FirstEditBox)
  989.       Gui.FirstEditBox->previous = p;
  990.    Gui.FirstEditBox = p;
  991.  
  992.     if (p->hidden == 0 && !ForSubList)
  993.         {
  994.        AddGadget(win->Win, &p->editbox, -1);
  995.         RefreshGList(&p->editbox, win->Win, NULL, 1);
  996.         }
  997.  
  998.    Diagnostic("CreateEditBox", EXIT, TRUE);
  999.    return p;
  1000.    }
  1001.  
  1002. EditBox* FOXLIB MakeEditBox(REGA0 void *Parent, REGD0 int x, REGD1 int y, REGD2 int len, REGD3 int buflen,
  1003.         REGD4 int id, REGA1 BOOL (* __far __stdargs callfn) (EditBox*), REGD5 long flags, REGA2 void *extension)       /* Tcol must be between 0 & 7 */
  1004.    {
  1005.     int type;
  1006.    EditBox *p;
  1007.  
  1008.    Diagnostic("MakeEditBox", ENTER, TRUE);
  1009.  
  1010.     // Extract the edit box type from the flags
  1011.     if (flags & NO_EDIT)
  1012.         type = NO_EDIT;
  1013.     else if (flags & FLOAT_EDIT)
  1014.         type = FLOAT_EDIT;
  1015.     else if (flags & INT_EDIT)
  1016.         type = INT_EDIT;
  1017.     else
  1018.         type = TEXT_EDIT;
  1019.  
  1020.    p = CreateEditBox(Parent, x, y, len, buflen, Gui.BorderCol, Gui.BackCol, Gui.TextCol, type, id, callfn, FALSE, FALSE, flags);
  1021.    if (p)
  1022.       Diagnostic("MakeEditBox", EXIT, TRUE);
  1023.    else
  1024.       Diagnostic("MakeEditBox", EXIT, FALSE);
  1025.    return p;
  1026.    }
  1027.  
  1028. BOOL FOXLIB SetDDListBoxPopup(REGA0 DDListBox *l, REGD0 int x, REGD1 int y, REGD2 int width, REGD3 int height)
  1029.    {
  1030.    Diagnostic("SetDDListBoxPopup", ENTER, TRUE);
  1031.     if (l && l->list && height && width)
  1032.         {
  1033.         int fontheight = GuiFont.ta_YSize; //GetFontHeight(GUIWIN(l));
  1034.  
  1035.         if ((height * fontheight) + 3 + y > GUIWIN(l)->ParentScreen->Height || width >
  1036.                 GUIWIN(l)->ParentScreen->Width)   /* Won't fit on screen when opened */
  1037.           return Diagnostic("SetDDListBoxPopup", EXIT, FALSE);
  1038.        l->list->PopupWidth = width;
  1039.        l->list->MaxHeight = height;
  1040.        l->list->PopupX = x;
  1041.        l->list->PopupY = y;
  1042.        return Diagnostic("SetDDListBoxPopup", EXIT, TRUE);
  1043.         }
  1044.     else
  1045.          return Diagnostic("SetDDListBoxPopup", EXIT, FALSE);
  1046.    }
  1047.  
  1048. BOOL FOXLIB AssociateDDListBox(REGA0 DDListBox *l, REGA1 DDListBox *m)
  1049.     {
  1050.    Diagnostic("AssociateDDListBox", ENTER, TRUE);
  1051.     if (!(l->list))
  1052.         return Diagnostic("AssociateDDListBox", EXIT, FALSE);
  1053.     if (l->NextAssociated || l->PreviousAssociated || l->list->first)
  1054.         return Diagnostic("AssociateDDListBox", EXIT, FALSE);
  1055.  
  1056.     GuiFree(l->list);
  1057.     l->list = m->list;
  1058.     l->NextAssociated = m->NextAssociated;
  1059.     l->PreviousAssociated = m;
  1060.     if (m->NextAssociated)
  1061.         m->NextAssociated->PreviousAssociated = l;
  1062.     m->NextAssociated = l;
  1063.     return Diagnostic("AssociateDDListBox", EXIT, TRUE);
  1064.     }
  1065.  
  1066. void FOXLIB ClearDDListBox(REGA0 DDListBox *l)
  1067.    {
  1068.    struct ListElement *p = l->list->first, *n;
  1069.    Diagnostic("ClearDDListBox", ENTER, TRUE);
  1070. //    if (l->NextAssociated == NULL && l->PreviousAssociated == NULL)
  1071. //        {
  1072.       while (p)
  1073.          {
  1074.          n = p->Next;
  1075.          GuiFree(p->string);
  1076.             if (p->Child)
  1077.                 {
  1078.                 /* If there is a child then the call to DestroyDDListBox() for that child will attempt
  1079.                     to sever the link from the parent (this list) to it's child.  To do that it will have
  1080.                     to navigate through the list looking for the parent element.  That would cause all sorts
  1081.                     of problems because we've already started freeing the list so we'd better set the
  1082.                     child's parent to NULL. */
  1083.                 if (p->Child->list)
  1084.                     p->Child->list->Parent = NULL;
  1085.                 DestroyDDListBox((DDListBox *) p->Child, FALSE);
  1086.                 }
  1087.          GuiFree(p);
  1088.          p = n;
  1089.          }
  1090.       l->list->first = NULL;
  1091.       l->list->TotalElems = 0;
  1092. //        }
  1093.    Diagnostic("ClearDDListBox", EXIT, TRUE);
  1094.    }
  1095.  
  1096. BOOL FOXLIB RemoveFromDDListBox(REGA0 DDListBox *list, REGA1 char *str)      /* Returns TRUE if successful */
  1097.    {
  1098.    int i = 1;
  1099.    struct ListElement *old, *previous = NULL;
  1100.    Diagnostic("RemoveFromDDListBox", ENTER, TRUE);
  1101.    if (!list)
  1102.       return Diagnostic("RemoveFromDDListBox", EXIT, FALSE);
  1103.    if (!(list->list))
  1104.       return Diagnostic("RemoveFromDDListBox", EXIT, FALSE);
  1105. //    if (list->NextAssociated || list->PreviousAssociated)
  1106. //        return Diagnostic("RemoveFromDDListBox", EXIT, FALSE);
  1107.    old = list->list->first;
  1108.    while (old)
  1109.       {
  1110.       if (!strcmp(old->string, str))
  1111.          break;
  1112.       else
  1113.          {
  1114.          previous = old;
  1115.          old = old->Next;
  1116.          }
  1117.       }
  1118.    if (!old)
  1119.       return Diagnostic("RemoveFromDDListBox", EXIT, FALSE);
  1120.    if (previous)
  1121.       previous->Next = old->Next;
  1122.    else
  1123.       list->list->first = old->Next;
  1124.    list->list->TotalElems--;
  1125.    GuiFree(old->string);
  1126.    if (old->Child)
  1127.       DestroyDDListBox((DDListBox *) old->Child, FALSE);
  1128.    GuiFree(old);
  1129.    old = list->list->first;
  1130.    while (old)
  1131.       {
  1132.       old->Itemnum = i++;
  1133.       old = old->Next;
  1134.       }
  1135.    return Diagnostic("RemoveFromDDListBox", EXIT, TRUE);
  1136.    }
  1137.  
  1138. BOOL FOXLIB AddToDDListBox(REGA0 DDListBox *list, REGA1 char *str)      /* Returns TRUE if successful */
  1139.    {
  1140.    struct ListElement *le, *p, *f;
  1141.    Diagnostic("AddToDDListBox", ENTER, TRUE);
  1142.    if (!list)
  1143.       {
  1144.       SetLastErr("NULL DDListBox pointer sent to AddToDDListBox().");
  1145.       return Diagnostic("AddToDDListBox", EXIT, FALSE);
  1146.       }
  1147.    if (!(list->list))
  1148.       return Diagnostic("AddToDDListBox", EXIT, FALSE);
  1149.    if (!(le = (struct ListElement *) GuiMalloc(sizeof(struct ListElement), 0)))
  1150.       return Diagnostic("AddToDDListBox", EXIT, FALSE);
  1151.    if (!(le->string = (char *) GuiMalloc((strlen(str) + 1) * sizeof(char), 0)))
  1152.       {
  1153.       GuiFree(le);
  1154.       return Diagnostic("AddToDDListBox", EXIT, FALSE);
  1155.       }
  1156.    strcpy(le->string, str);
  1157.    le->Next = NULL;
  1158.    le->Child = NULL;
  1159.    le->Itemnum = ++(list->list->TotalElems);
  1160.    p = list->list->first;
  1161.    f = NULL;
  1162.    while (p)
  1163.       {
  1164.       f = p;
  1165.       p = p->Next;
  1166.       }
  1167.    if (!f)
  1168.       list->list->first = le;
  1169.    else
  1170.       f->Next = le;
  1171.    return Diagnostic("AddToDDListBox", EXIT, TRUE);
  1172.    }
  1173.  
  1174. static void UndrawDDListBox(DDListBox *p)
  1175.     {
  1176.     int fontheight = GetFontHeight(GUIWIN(p));
  1177.     AreaColFill(GUIWIN(p)->Win->RPort, p->WidgetData->left, p->WidgetData->top, p->WidgetData->width + DD_LIST_BOX_BUTTON_WIDTH, fontheight + 2,
  1178.             GetBackCol(p->WidgetData->Parent));
  1179.     }
  1180.  
  1181. BOOL ShowDDListBox(DDListBox *p)
  1182.     {
  1183.     Diagnostic("ShowDDListBox", ENTER, TRUE);
  1184.     if (p && p->list)
  1185.         {
  1186.         struct Window *w = GUIWIN(p)->Win;
  1187.  
  1188.         if (p->hidden == 1) // The drop-down list box is really hidden.
  1189.             if ((!ISGUIWINDOW(p->WidgetData->Parent)) && ((Frame *) p->WidgetData->Parent)->hidden != 0)
  1190.                 p->hidden = -1; // The drop-down list box is in a hidden frame so it will remain hidden
  1191.             else
  1192.                 {
  1193.                 BOOL prefound, nextfound;
  1194.                 UWORD prepos, nextpos, pos;
  1195.  
  1196.                 FindPreviousNext(p, &prefound, &nextfound, &prepos, &nextpos);
  1197.                 // The gadget is not in the list so we need to add it.
  1198.                 if (nextfound)
  1199.                     pos = nextpos + 1;
  1200.                 else if (prefound)
  1201.                     pos = prepos;
  1202.                 else
  1203.                     pos = (unsigned short) ~0; // Add to the end of the list because we couldn't find the right place.
  1204.                 AddGadget(w, &p->editbox, pos);
  1205.                 p->hidden = 0;
  1206.                 }
  1207.         if (p->hidden == 0)
  1208.             {
  1209.             // Refresh the gadget
  1210.             RefreshGList(&p->editbox, w, NULL, 1);
  1211.             if (Gui.LibVersion < A3000)
  1212.                 RemoveGadget(w, &p->editbox);
  1213.             }
  1214.         return Diagnostic("ShowDDListBox", EXIT, TRUE);
  1215.         }
  1216.     return Diagnostic("ShowDDListBox", EXIT, FALSE);
  1217.     }
  1218.  
  1219. BOOL HideDDListBox(DDListBox *p)
  1220.     {
  1221.     Diagnostic("HideDDListBox", ENTER, TRUE);
  1222.     if (p && p->list)
  1223.         {
  1224.         if (p->hidden == 0)
  1225.             {
  1226.             UndrawDDListBox(p);
  1227.             if (Gui.LibVersion >= A3000)
  1228.                 RemoveGadget(GUIWIN(p)->Win, &(p->editbox));
  1229.             }
  1230.         p->hidden = 1;
  1231.         return Diagnostic("HideDDListBox", EXIT, TRUE);
  1232.         }
  1233.     return Diagnostic("HideDDListBox", EXIT, FALSE);
  1234.     }
  1235.  
  1236. void DestroyDDListBox(DDListBox *p, BOOL refresh)
  1237.    {
  1238.    Diagnostic("DestroyDDListBox", ENTER, TRUE);
  1239.    if (p && p->list)
  1240.       {
  1241.         Frame *Child; // Could be any control type
  1242.  
  1243.         if (p->NextAssociated == NULL && p->PreviousAssociated == NULL)
  1244.             {
  1245.             ClearDDListBox(p);
  1246.             if (p->list->Parent)
  1247.                 {
  1248.                 struct ListElement *e = p->list->Parent->list->first;
  1249.                 while (e)
  1250.                     {
  1251.                     if (e->Child == p)
  1252.                         break;
  1253.                     e = e->Next;
  1254.                     }
  1255.                 if (e)
  1256.                     e->Child = NULL;
  1257.                 }
  1258.             GuiFree(p->list);
  1259.             }
  1260.         else
  1261.             {
  1262.             // Remove this drop-down list from the association list.
  1263.             if (p->PreviousAssociated)
  1264.                 p->PreviousAssociated->NextAssociated = p->NextAssociated;
  1265.             if (p->NextAssociated)
  1266.                 p->NextAssociated->PreviousAssociated = p->PreviousAssociated;
  1267.             }
  1268.         p->list = NULL;
  1269.  
  1270.         /* On an A500, the gadget won't be in the list but DestroyEditBox() will attempt to remove it
  1271.             from the list, so add it back here. */
  1272.         if (Gui.LibVersion < A3000)
  1273.             AddGadget(GUIWIN(p)->Win, &(p->editbox), -1);
  1274.  
  1275.         if (refresh && p->hidden == 0)
  1276.             UndrawDDListBox(p);
  1277.         Child = p->WidgetData->ChildWidget;
  1278.         while (Child)
  1279.             {
  1280.             void *next = Child->WidgetData->NextWidget;
  1281.             Child->WidgetData->ParentControl = NULL; // Otherwise destroy will fail.
  1282.             Destroy(Child, refresh);
  1283.             Child = next;
  1284.             }
  1285.       DestroyEditBox(p, FALSE);
  1286.       }
  1287.    Diagnostic("DestroyDDListBox", EXIT, TRUE);
  1288.    }
  1289.  
  1290. void DestroyAllDDListBoxes(BOOL refresh)
  1291.    {
  1292.    struct EditBoxStruct *p;
  1293.    Diagnostic("DestroyAllDDListBoxes", ENTER, TRUE);
  1294.    p = Gui.FirstEditBox;
  1295.    while (p)
  1296.       {
  1297.         if (p->list)
  1298.             {
  1299.           DestroyDDListBox(p, refresh);
  1300.             p = Gui.FirstEditBox;
  1301.             }
  1302.         else
  1303.             p = p->next;
  1304.       }
  1305.    Diagnostic("DestroyAllDDListBoxes", EXIT, TRUE);
  1306.    }
  1307.  
  1308. void DestroyWinDDListBoxes(GuiWindow *c, BOOL refresh)
  1309.    {
  1310.     BOOL message = FALSE;
  1311.    struct EditBoxStruct *p;
  1312.    Diagnostic("DestroyWinDDListBoxes", ENTER, TRUE);
  1313.    p = Gui.FirstEditBox;
  1314.    while (p)
  1315.       {
  1316.       if (GUIWIN(p) == c && p->list)
  1317.             {
  1318.          DestroyDDListBox((DDListBox *) p, refresh);
  1319.             message = TRUE;
  1320.             p = Gui.FirstEditBox;
  1321.             }
  1322.         else
  1323.             p = p->next;
  1324.       }
  1325.     if (Gui.CleanupFlag && message)
  1326.         SetLastErr("Window closed before all of its list boxes were destroyed.");
  1327.    Diagnostic("DestroyWinDDListBoxes", EXIT, TRUE);
  1328.    }
  1329.  
  1330. static DDListBox *CreateDDListBox(void *Parent, int x, int y, int len, int buflen, int maxheight, int BorderCol, int Bcol, int Tcol, int id, BOOL (*callfn) (DDListBox*), BOOL ForSubListBox, long flags)
  1331.    {
  1332.    DDListBox *p;
  1333.    struct DDListBoxStruct *l;
  1334.     int winheight, fontheight, xoffset = 0, yoffset = 0;
  1335.     GuiWindow *win;
  1336.  
  1337.    Diagnostic("CreateDDListBox", ENTER, TRUE);
  1338.  
  1339.    if (x < 0 || y < 0 || !Parent)
  1340.         {
  1341.        Diagnostic("CreateDDListBox", EXIT, FALSE);
  1342.         return NULL;
  1343.         }
  1344.  
  1345.     if (!ISGUIWINDOW(Parent))
  1346.         {
  1347.         xoffset = ((Frame *) Parent)->button.LeftEdge;
  1348.         yoffset = ((Frame *) Parent)->button.TopEdge;
  1349.         win = (GuiWindow *) ((Frame *) Parent)->button.UserData;
  1350.         }
  1351.     else
  1352.         win = (GuiWindow *) Parent;
  1353.  
  1354.     fontheight = GetFontHeight(win);
  1355.     winheight = (maxheight * fontheight) + 3;
  1356.    if (!ForSubListBox)
  1357.       {
  1358.       if (y + yoffset + win->Win->TopEdge + fontheight + 2 > win->ParentScreen->Height || /* Box is too low down */
  1359.             x + xoffset + win->Win->LeftEdge + len + DD_LIST_BOX_BUTTON_WIDTH - 1 > win->ParentScreen->Width) /* Box is too wide or too far right */
  1360.          {
  1361.          Diagnostic("CreateDDListBox", EXIT, FALSE);
  1362.          return NULL;
  1363.          }
  1364.       if (win->Win->TopEdge + y + yoffset + fontheight + 2 + winheight > win->ParentScreen->Height) /* Box cannot drop below - try above */
  1365.          if (win->Win->TopEdge + y + yoffset - winheight < 0) /* Box Can't drop above */
  1366.             {
  1367.             Diagnostic("CreateDDListBox", EXIT, FALSE);
  1368.             return NULL;
  1369.             }
  1370.       }
  1371.    l = (struct DDListBoxStruct *) GuiMalloc(sizeof(struct DDListBoxStruct), MEMF_CLEAR);
  1372.    if (!l)
  1373.       {
  1374.       Diagnostic("CreateDDListBox", EXIT, FALSE);
  1375.       return NULL;
  1376.       }
  1377.    p = (DDListBox *) CreateEditBox(Parent, x, y, len, buflen, BorderCol, Bcol, Tcol, NO_EDIT, id, callfn, TRUE, ForSubListBox, flags);
  1378.    if (!p)
  1379.       {
  1380.       GuiFree(l);
  1381.       Diagnostic("CreateDDListBox", EXIT, FALSE);
  1382.       return NULL;
  1383.       }
  1384.    p->list = l;
  1385.    l->MaxHeight = maxheight;
  1386.    l->TotalElems = 0;
  1387.  
  1388.     /* On an A500, we mustn't allow the user to edit the contents of the list box (since edit hooks
  1389.         aren't supported) so we need to remove the gadget to prevent the user from editing it. */
  1390.     if (Gui.LibVersion < A3000)
  1391.         RemoveGList(GUIWIN(p)->Win, &p->editbox, 1);
  1392.  
  1393.    Diagnostic("CreateDDListBox", EXIT, TRUE);
  1394.    return p;
  1395.    }
  1396.  
  1397. DDListBox* FOXLIB MakeDDListBox(REGA0 void *Parent, REGD0 int x, REGD1 int y, REGD2 int len, REGD3 int buflen,
  1398.     REGD4 int MaxHeight, REGD5 int id, REGA1 BOOL (* __far __stdargs callfn) (DDListBox*), REGD6 long flags, REGA2 void *extension)       /* Tcol must be between 0 & 7 */
  1399.    {
  1400.    DDListBox *p;
  1401.    Diagnostic("MakeDDListBox", ENTER, TRUE);
  1402.  
  1403.     p = CreateDDListBox(Parent, x, y, len, buflen, MaxHeight, Gui.BorderCol, Gui.BackCol, Gui.TextCol, id, callfn, FALSE, flags);
  1404.    if (p)
  1405.       Diagnostic("MakeDDListBox", EXIT, TRUE);
  1406.    else
  1407.       Diagnostic("MakeDDListBox", EXIT, FALSE);
  1408.    return p;
  1409.    }
  1410.  
  1411. DDListBox* FOXLIB MakeSubDDListBox(REGA0 DDListBox *lb, REGA1 char *string, REGD0 int left, REGD1 int top, REGD2 int width,
  1412.         REGD3 int height, REGD4 int id, REGA2 BOOL (* __far __stdargs callfn)(DDListBox*), REGA3 void *extension)
  1413.    {
  1414.    DDListBox *l;
  1415.    struct ListElement *i;
  1416.    int TextHeight = max((height / 8) - 1, 1);
  1417.    Diagnostic("MakeSubDDListBox", ENTER, TRUE);
  1418.    if ((!lb) || (!lb->list) || !string)
  1419.       {
  1420.       Diagnostic("MakeSubDDListBox", EXIT, FALSE);
  1421.       return NULL;
  1422.       }
  1423.    i = lb->list->first;
  1424.    while (i)
  1425.       {
  1426.       if (!strcmp(i->string, string))
  1427.          break;
  1428.       else
  1429.          i = i->Next;
  1430.       }
  1431.    if (!i)
  1432.       {
  1433.       AddToDDListBox(lb, string);
  1434.       i = lb->list->first;
  1435.       while (i)
  1436.          {
  1437.          if (!strcmp(i->string, string))
  1438.             break;
  1439.          else
  1440.             i = i->Next;
  1441.          }
  1442.       }
  1443.    if (!i)   /* AddToDDListBox must have failed */
  1444.       {
  1445.       Diagnostic("MakeSubDDListBox", EXIT, FALSE);
  1446.       return NULL;
  1447.       }
  1448.    if (i->Child)
  1449.       {
  1450.       Diagnostic("MakeSubDDListBox", EXIT, FALSE);
  1451.       return NULL;
  1452.       }
  1453.     l = CreateDDListBox(GUIWIN(lb), 1, 0, 0, 0, TextHeight, lb->lborder.FrontPen, lb->Bcol, lb->Tcol, id, callfn, TRUE, 0);
  1454.    if (!l)
  1455.       {
  1456.       Diagnostic("MakeSubDDListBox", EXIT, FALSE);
  1457.       return NULL;
  1458.       }
  1459.    if (!SetDDListBoxPopup(l, left, top, width, height))
  1460.       {
  1461.       DestroyDDListBox(l, FALSE);
  1462.       Diagnostic("MakeSubDDListBox", EXIT, FALSE);
  1463.       return NULL;
  1464.       }
  1465.    i->Child = l;
  1466.    l->list->Parent = lb;
  1467.    Diagnostic("MakeSubDDListBox", EXIT, TRUE);
  1468.    return l;
  1469.    }
  1470.  
  1471. void FOXLIB SetOutputBoxDP(REGA0 OutputBox *p, REGD0 int dp)
  1472.    {
  1473.    Diagnostic("SetOutputBoxDP", ENTER, TRUE);
  1474.    p->dp = dp;
  1475.    Diagnostic("SetOutputBoxDP", EXIT, TRUE);
  1476.    }
  1477.  
  1478. void FOXLIB SetOutputBoxInt(REGA0 OutputBox *p, REGD0 int num)
  1479.    {
  1480.    char str[MAX_EDIT_BOX_LEN + 1];
  1481.    Diagnostic("SetOutputBoxInt", ENTER, TRUE);
  1482.    sprintf(str, "%d", num);
  1483.    SetOutputBoxText(p, str);
  1484.    Diagnostic("SetOutputBoxInt", EXIT, TRUE);
  1485.    }
  1486.  
  1487. BOOL HideOutputBox(OutputBox *p)
  1488.     {
  1489.     Diagnostic("HideOutputBox", ENTER, TRUE);
  1490.     if (p)
  1491.         {
  1492.         if (p->hidden == 0)
  1493.             {
  1494.             int width;
  1495.             BYTE BackCol = GetBackCol(p->WidgetData->Parent);
  1496.  
  1497.             // Work out the width of the output box.
  1498.             if (p->dborder.Count == 0)            // The output box has a 2d border or no border at all.
  1499.                 width = p->points[2] + 1;
  1500.             else                                        // The output box has a 3d border.
  1501.                 width = p->points[12] + 1;
  1502.             AreaColFill(p->win->Win->RPort, p->lborder.LeftEdge, p->lborder.TopEdge, width,
  1503.                     p->font->ta_YSize + 2, BackCol);
  1504.             }
  1505.         p->hidden = 1;
  1506.         return Diagnostic("HideOutputBox", EXIT, TRUE);
  1507.         }
  1508.     return Diagnostic("HideOutputBox", EXIT, FALSE);
  1509.     }
  1510.  
  1511. void DestroyOutputBox(OutputBox *p, BOOL refresh)
  1512.    {
  1513.    Diagnostic("DestroyOutputBox", ENTER, TRUE);
  1514.    if (p && p->WidgetData->ParentControl == NULL)
  1515.       {
  1516.         Frame *Child; // Could be any control type
  1517.       OutputBox *n = p->next;
  1518.       if (p == Gui.FirstOutputBox)
  1519.          Gui.FirstOutputBox = n;
  1520.       if (n)
  1521.          n->previous = p->previous;
  1522.       if (p->previous)
  1523.          p->previous->next = n;
  1524.         GuiFree(p->text);
  1525.  
  1526.         if (refresh)
  1527.             HideOutputBox(p);
  1528.  
  1529.         if (p->WidgetData->os)
  1530.             GuiFree(p->WidgetData->os);
  1531.         if (p->font)
  1532.             {
  1533.             if (p->font->ta_Name)
  1534.                 GuiFree(p->font->ta_Name);
  1535.             GuiFree(p->font);
  1536.             }
  1537.         Child = p->WidgetData->ChildWidget;
  1538.         while (Child)
  1539.             {
  1540.             Widget *next = Child->WidgetData->NextWidget;
  1541.             Child->WidgetData->ParentControl = NULL; // Otherwise destroy will fail.
  1542.             Destroy(Child, refresh);
  1543.             Child = next;
  1544.             }
  1545.       GuiFree(p->WidgetData);
  1546.       GuiFree(p);
  1547.       }
  1548.    Diagnostic("DestroyOutputBox", EXIT, TRUE);
  1549.    }
  1550.  
  1551. void DestroyAllOutputBoxes(BOOL refresh)
  1552.    {
  1553.    OutputBox *p;
  1554.    Diagnostic("DestroyAllOutputBoxes", ENTER, TRUE);
  1555.    p = Gui.FirstOutputBox;
  1556.    while (p)
  1557.       {
  1558.         OutputBox *next = p->next;
  1559.       DestroyOutputBox(p, refresh);
  1560.       p = next;
  1561.       }
  1562.    Diagnostic("DestroyAllOutputBoxes", EXIT, TRUE);
  1563.    }
  1564.  
  1565. void DestroyWinOutputBoxes(GuiWindow *c, BOOL refresh)
  1566.    {
  1567.     BOOL message = FALSE;
  1568.    OutputBox *p;
  1569.    Diagnostic("DestroyWinOutputBoxes", ENTER, TRUE);
  1570.    p = Gui.FirstOutputBox;
  1571.    while (p)
  1572.       {
  1573.         OutputBox *next = p->next;
  1574.       if (p->win == c)
  1575.          {
  1576.          DestroyOutputBox(p, refresh);
  1577.             message = TRUE;
  1578.          }
  1579.       p = next;
  1580.       }
  1581.     if (Gui.CleanupFlag && message)
  1582.         SetLastErr("Window closed before all of its output boxes were destroyed.");
  1583.    Diagnostic("DestroyWinOutputBoxes", EXIT, TRUE);
  1584.    }
  1585.  
  1586. void DoubleToString(char *str, double dbl, int dp)
  1587. {
  1588.     double whole = floor(dbl);
  1589.     double remain = dbl - whole, dec;
  1590.     int n;
  1591.  
  1592.     for (n = 0; n < dp; n++)
  1593.         remain *= 10;
  1594.  
  1595.     dec = floor(remain);
  1596.     sprintf(str, "%d.%d", (int) whole, (int) dec);
  1597. }
  1598.  
  1599. void FOXLIB SetOutputBoxDouble(REGA0 OutputBox *p, REGD0 double num)
  1600.    {
  1601.    char str[MAX_EDIT_BOX_LEN + 1];
  1602.    Diagnostic("SetOutputBoxDouble", ENTER, TRUE);
  1603.     // We can't use sprintf because we have to link with sc.lib before scmieee.lib and
  1604.     // the version of sprintf in sc.lib doesn't support floats or doubles.
  1605.     DoubleToString(str, num, p->dp);
  1606.    SetOutputBoxText(p, str);
  1607.    Diagnostic("SetOutputBoxDouble", EXIT, TRUE);
  1608.    }
  1609.  
  1610. double GetDoubleFromStr(char *str)
  1611.    {
  1612.    double num = 0.0, pnum = 1;
  1613.    int neg = 1, ptr;
  1614.    for (ptr = 0; ptr < strlen(str) && str[ptr] != '.'; ptr++)
  1615.       if (str[ptr] == '-')
  1616.          neg = -1;
  1617.       else
  1618.          num = (num * 10.0) + str[ptr] - '0';
  1619.    if (str[ptr++] == '.')
  1620.       for (; ptr < strlen(str); ptr++)
  1621.          num += (pnum /= 10.0) * (str[ptr] - '0');
  1622.    num *= neg;
  1623.    return num;
  1624.    }
  1625.  
  1626. double FOXLIB GetEditBoxDouble(REGA0 EditBox *p)
  1627.    {
  1628.    Diagnostic("GetEditBoxDouble", ENTER, TRUE);
  1629.    if (!p)
  1630.       {
  1631.       Diagnostic("GetEditBoxDouble", EXIT, FALSE);
  1632.       return 0.0;
  1633.       }
  1634.    Diagnostic("GetEditBoxDouble", EXIT, TRUE);
  1635.    return GetDoubleFromStr(p->buffer);
  1636.    }
  1637.  
  1638. BOOL FOXLIB SetEditBoxDouble(REGA0 EditBox *p, REGD0 double num)
  1639.    {
  1640.    BOOL retval;
  1641.    char str[30];
  1642.    Diagnostic("SetEditBoxDouble", ENTER, TRUE);
  1643.    if (!p)
  1644.       return Diagnostic("SetEditBoxDouble", EXIT, FALSE);
  1645.     // We can't use sprintf because we have to link with sc.lib before scmieee.lib and
  1646.     // the version of sprintf in sc.lib doesn't support floats or doubles.
  1647.     DoubleToString(str, num, p->dp);
  1648.    retval = SetEditBoxText(p, str);
  1649.    return Diagnostic("SetEditBoxDouble", EXIT, retval);
  1650.    }
  1651.  
  1652. BOOL FOXLIB SetDDListBoxText(REGA0 DDListBox *l, REGA1 char *c)
  1653. {
  1654.     return SetEditBoxText((EditBox *) l, c);
  1655. }
  1656.  
  1657. char* FOXLIB GetDDListBoxText(REGA0 DDListBox *l)
  1658. {
  1659.     return GetEditBoxText((EditBox*) l);
  1660. }
  1661.  
  1662. int FOXLIB GetEditBoxID(REGA0 EditBox *p)
  1663. {
  1664.     return p->id;
  1665. }
  1666.  
  1667. int FOXLIB GetDDListBoxID(REGA0 DDListBox *l)
  1668. {
  1669.     return l->id;
  1670. }
  1671.